using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Shinkansen.Core;
using Shinkansen.Runtime;
using Shinkansen.Support;
using Shinkansen.Web.UI.WebControls;

namespace Shinkansen.Model
{
    public class CombinedQueryStringBuilder : IQueryStringBuilder
    {
        private readonly IEnumerable<IStaticInclude> _resources;
        private readonly PathResolver _pathResolver = new PathResolver ();

        /// <summary>
        /// Initializes a new instance of the <see cref="CombinedQueryStringBuilder"/> class.
        /// </summary>
        /// <param name="resources">The resources.</param>
        public CombinedQueryStringBuilder (IEnumerable<IStaticInclude> resources)
        {
            _resources = resources;
        }

        /// <summary>
        /// Builds the specified query string.
        /// </summary>
        /// <param name="queryString">The query string.</param>
        public void ConstructQueryString (QueryString queryString)
        {
            List<long> ticks = new List<long> ();
            List<string> paths = new List<string> ();

            foreach (IStaticInclude include in _resources)
            {
                string absolutePath = _pathResolver.ToAbsolute (include.Path);
                string physicalPath = _pathResolver.ToPhysical (absolutePath);

                if (!File.Exists (physicalPath))
                    throw new FileNotFoundException (string.Format ("File '{0}' is not found.", absolutePath));

                paths.Add (absolutePath);
                ticks.Add (File.GetLastWriteTime (physicalPath).Ticks);
            }

            string combinedPaths = string.Join ("|", paths.ToArray ());
            string combinedTicks = ticks.Aggregate (
                new StringBuilder (),
                (acc, b) => acc.Append (b),
                r => r.ToString ());

            string tickHash = new Cryptography ().GenerateMD5Hash (combinedTicks);

            queryString[Tokens.Path] = combinedPaths;
            queryString[Tokens.Timestamp] = tickHash;
        }
    }
}